package cn.tedu.luban.worker.main.repository;

import cn.tedu.luban.worker.main.converter.WorkerConverter;
import cn.tedu.luban.worker.main.mapper.WorkerMapper;
import cn.tedu.luban.worker.protocol.bo.AdminWorkerBO;
import cn.tedu.luban.worker.protocol.bo.FrontWorkerBO;
import cn.tedu.luban.worker.protocol.dos.WorkerDO;
import cn.tedu.luban.worker.protocol.param.WorkerParam;
import cn.tedu.luban.worker.protocol.param.WorkerRegistParam;
import cn.tedu.luban.worker.protocol.query.WorkerDBPageQuery;
import cn.tedu.luban.worker.protocol.query.WorkerListQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Repository
@Slf4j
public class WorkerRepoImpl implements WorkerRepository{

    @Autowired(required = false)
    private WorkerMapper workerMapper;

    private static final String WORKER_KEY_PREFIX = "luban:worker:detail:";

    @Override
    public void deleteByUserId(Long userId) {
        workerMapper.deleteByUserId(userId);
        // 删除 redis缓存
        redisTemplate.delete(WORKER_KEY_PREFIX + userId);
    }


    @Autowired
    private WorkerConverter workerConverter;

    @Override
    public Long save(WorkerRegistParam param) {
        // 1.param里的师傅数据 取出转换成workerDO对象
        WorkerDO workerDO = workerConverter.param2do(param);
        // 2.调用持久层写入workerDO对象
        workerMapper.insert(workerDO);
        // 3.返回workerId
        return workerDO.getId();
    }

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public FrontWorkerBO getWorkerByUserId(Long userId) {
        // 引入缓存逻辑
        ValueOperations ops = redisTemplate.opsForValue();

        // 定义缓存key
        String workerKey = WORKER_KEY_PREFIX + userId;
        // 查询缓存 存在key返回true，否则反之
        Boolean hasKey = redisTemplate.hasKey(workerKey);

        FrontWorkerBO workerBO = null;
        // 判断是否命中
        if(hasKey){
            log.info("命中缓存，直接返回缓存数据");
            workerBO = (FrontWorkerBO)ops.get(workerKey);
        }else{
            log.info("未命中缓存，查询数据库");
            // 调用持久成获取workerDO对象
            WorkerDO workerDO = workerMapper.selectByUserId(userId);
            // 转换成前端需要的对象
            workerBO = workerConverter.do2frontBo(workerDO);
            // 补充缓存(是否允许永久存储)、设置超时时间(24小时) 超时后会自动删除
            ops.set(workerKey,workerBO,1000*60*60*24 + new Random().nextInt(1000*60*60*12), TimeUnit.MILLISECONDS);
        }
        return workerBO;
    }

    @Override
    public Long countWorker(WorkerListQuery query) {
        // 入参query对象 不是持久层的查询参数，需要转化成持久层的查询参数dbQuery
        WorkerDBPageQuery dbQuery = workerConverter.query2dbQuery(query);
        // 利用页码与行数 拼接limit关键字
        String limit = dbQuery.getLimit();
        log.info("dbQuery 拼接参的limit参数:{}",limit);
        // 调用持久层查询总数
        Long total = workerMapper.countWorker(dbQuery);
        return total;
    }

    @Override
    public List<AdminWorkerBO> findPageWorkers(WorkerListQuery query) {
        // 入参query对象 不是持久层的查询参数，需要转化成持久层的查询参数dbQuery
        WorkerDBPageQuery dbQuery = workerConverter.query2dbQuery(query);
        List<WorkerDO> dos = workerMapper.selectWorkers(dbQuery);
        return workerConverter.dos2bos(dos);
    }

    @Override
    public AdminWorkerBO findAdminWorker(Long userId) {
        WorkerDO workerDO = workerMapper.selectByUserId(userId);
        return workerConverter.do2bo(workerDO);
    }


    @Override
    public void updateAuditStatus(WorkerParam workerParam) {
        log.info("WorkerParam.updateAuditStatus入参：{}",workerParam);
        WorkerDO workerDO = workerConverter.param2do(workerParam);
        workerMapper.updateAuditStatus(workerDO);
        // 更新缓存 数据一致性
        redisTemplate.delete(WORKER_KEY_PREFIX + workerParam.getUserId());
    }

    @Override
    public void updateCertStatus(WorkerParam workerParam) {
        WorkerDO workerDO = workerConverter.param2do(workerParam);
        workerMapper.updateCertStatus(workerDO);
        // 更新缓存 数据一致性
        redisTemplate.delete(WORKER_KEY_PREFIX + workerParam.getUserId());
    }
}
